package com.cst.intercepterdemo.chain.expression.parser;

import com.cst.intercepterdemo.chain.expression.DefaultExpression;
import com.cst.intercepterdemo.chain.expression.IExpression;
import com.cst.intercepterdemo.exceptions.ExpressionNotCorrectException;
import org.springframework.util.StringUtils;

/**
 * <ul>
 * <li>文件名称 : com.cst.intercepterdemo.chain.expression.Parser
 * </li>
 * <li>版权所有 : 版权所有(C)2016-2020</li>
 * <li>公 司 : CST</li>
 * <li>创建时间 : 2016/12/5</li>
 * <li>修改记录 : </li>
 * </ul>
 * 类说明：表达式解析器
 *
 * @author Allen
 * @version 1.0
 */
public class DefaultExpressionParser implements IExpressionParser {

    private static final char PRE_QUOTE = '(';
    private static final char END_QUOTE = ')';

    @Override
    public IExpression parse(String expressionStr) {
        if(StringUtils.isEmpty(expressionStr)){
            throw new ExpressionNotCorrectException("expression should not be empty");
        }
        return parseExpression(expressionStr.toCharArray(),0,0);
    }

    /**
     * 迭代遍历表达式
     * @param expressions 表达式字符数组
     * @param startIndex 起始下标
     * @return 结束下标与当前表达式
     */
    public IExpression parseExpression(char[] expressions,Integer startIndex,Integer level){

        IExpression expression = new DefaultExpression();
        for(int i = startIndex ; i<expressions.length ; i++){
            char exChar = expressions[i];
            if(exChar == PRE_QUOTE){
                IExpression subExpression = parseExpression(expressions, i + 1, level + 1);
                expression.addSubExpression(subExpression);
                i = subExpression.getEndIndex();
            }else if(exChar == END_QUOTE){
                if(level==0){
                    throw new ExpressionNotCorrectException("quote not match in level 0");
                }
                expression.setStartIndex(startIndex);
                expression.setEndIndex(i);
                return expression;
            }
        }
        if(level != 0){
            throw new ExpressionNotCorrectException("miss back quote.");
        }
        expression.setStartIndex(startIndex);
        expression.setEndIndex(expressions.length);
        return expression;
    }
}